#include "fighthandler.h"
#include "game/matchroom.h"
#include "game/card.h"
#include "log.h"

static Logger::ptr lvqiang = LoggerMgr::GetInstance()->GetLogger("lvqiang");

void FightHandler::SetFightModel(const void* data, int size)
{
    m_fightModel.ParseFromArray(data, size);
}

void PutStakesCREQ(Player::ptr& player, MatchRoom::ptr& room, int stakes)
{
    proto::StakesResponse stakesResponse;
    stakesResponse.set_preplayerstakes(player->GetSeatPosition());
    stakesResponse.set_nextplayerposition(room->GetNextPlayer()->GetSeatPosition());
    stakesResponse.set_preplayerstakes(stakes);
    proto::FightModel fightModel;
    fightModel.set_fightcode(proto::FightCode::PutStakes_BRO);
    fightModel.set_msg(stakesResponse.SerializeAsString().c_str());
    proto::NetMsg netMsg;
    netMsg.set_opcode(proto::OpCode::Fight);
    netMsg.set_msg(fightModel.SerializeAsString().c_str());
    room->BroadCast(netMsg, false, player);
}

void LookCardCREQ(Player::ptr& player, MatchRoom::ptr& room)
{
    proto::LookCardResponse lookCardResponse;
    lookCardResponse.set_seatposition(player->GetSeatPosition());
    proto::FightModel fightModel;
    fightModel.set_fightcode(proto::FightCode::LookCard_BRO);
    fightModel.set_msg(lookCardResponse.SerializeAsString().c_str());
    proto::NetMsg netMsg;
    netMsg.set_opcode(proto::OpCode::Fight);
    netMsg.set_msg(fightModel.SerializeAsString().c_str());
    room->BroadCast(netMsg, false, player);
}

void GiveUpCardCREQ(Player::ptr& player, MatchRoom::ptr& room, int prePlayerStakes)
{
    proto::GiveUpResponse giveUpResponse;
    giveUpResponse.set_giveupposition(player->GetSeatPosition());
    giveUpResponse.set_preplayerstakes(prePlayerStakes);
    giveUpResponse.set_nextplayerposition(room->GetNextPlayer()->GetSeatPosition());
    proto::FightModel fightModel;
    fightModel.set_fightcode(proto::FightCode::GiveUpCard_BRO);
    fightModel.set_msg(giveUpResponse.SerializeAsString().c_str());
    proto::NetMsg netMsg;
    netMsg.set_opcode(proto::OpCode::Fight);
    netMsg.set_msg(fightModel.SerializeAsString().c_str());
    room->BroadCast(netMsg, false, player);
}

Player::ptr& CompareCardCREQ(Player::ptr& self, Player::ptr& opponent)
{
    if(self->GetCardType() > opponent->GetCardType())
    {
        return self;
    }
    else if(self->GetCardType() < opponent->GetCardType())
    {
        return opponent;
    }
    else
    {
        switch (self->GetCardType())
        {
            case proto::CardType::Max:
            {
                return opponent;
            }
            case proto::CardType::Baozi:
                {
                    Card::ptr selfCard = self->GetCards()[0];
                    Card::ptr opponentCard = opponent->GetCards()[0];
                    if(selfCard->GetWeight() > opponentCard->GetWeight())
                    {
                        return self;
                    }
                    else
                    {
                        return opponent;
                    }
                }
                break;
            case proto::CardType::Shunjin:
                {
                    Card::ptr selfCard = self->GetCards()[0];
                    Card::ptr opponentCard = opponent->GetCards()[0];
                    if(selfCard->GetWeight() > opponentCard->GetWeight())
                    {
                        return opponent;
                    }
                    else
                    {
                        return self;
                    }
                }
                break;
            case proto::CardType::Jinhua:
                {
                    std::vector<Card::ptr>& selfCards = self->GetCards();
                    std::vector<Card::ptr>& opponentCards = opponent->GetCards();
                    for(int i = 0; i < 3; i++)
                    {
                        if(selfCards[i]->GetWeight() == opponentCards[i]->GetWeight())
                        {
                            continue;
                        }
                        else if(selfCards[i]->GetWeight() > opponentCards[i]->GetWeight())
                        {
                            return self;
                        }
                        else
                        {
                            return opponent;
                        }
                    }
                }
                break;
            case proto::CardType::Shunzi:
                {
                    std::vector<Card::ptr>& selfCards = self->GetCards();
                    std::vector<Card::ptr>& opponentCards = opponent->GetCards();
                    for(int i = 0; i < 3; i++)
                    {
                        if(selfCards[i]->GetWeight() == opponentCards[i]->GetWeight())
                        {
                            continue;
                        }
                        else if(selfCards[i]->GetWeight() > opponentCards[i]->GetWeight())
                        {
                            return self;
                        }
                        else
                        {
                            return opponent;
                        }
                    }
                }
                break;
            case proto::CardType::Duizi:
                {
                    std::vector<Card::ptr>& selfCards = self->GetCards();
                    std::vector<Card::ptr>& opponentCards = opponent->GetCards();
                    if(selfCards[0]->GetWeight() == selfCards[1]->GetWeight() && 
                        opponentCards[0]->GetWeight() == opponentCards[1]->GetWeight())
                    {
                        if(selfCards[0]->GetWeight() == selfCards[0]->GetWeight())
                        {
                            if(selfCards[2]->GetWeight() > opponentCards[2]->GetWeight())
                            {
                                return self;
                            }
                            else
                            {
                                return opponent;
                            }
                        }
                        else if(selfCards[0]->GetWeight() > selfCards[0]->GetWeight())
                        {
                            return self;
                        }
                        else
                        {
                            return opponent;
                        }
                    }
                    if(selfCards[1]->GetWeight() == selfCards[2]->GetWeight() && 
                        opponentCards[1]->GetWeight() == opponentCards[2]->GetWeight())
                    {
                        if(selfCards[1]->GetWeight() == selfCards[1]->GetWeight())
                        {
                            if(selfCards[0]->GetWeight() > opponentCards[0]->GetWeight())
                            {
                                return self;
                            }
                            else
                            {
                                return opponent;
                            }
                        }
                        else if(selfCards[1]->GetWeight() > selfCards[1]->GetWeight())
                        {
                            return self;
                        }
                        else
                        {
                            return opponent;
                        }
                    }
                }
                break;
            case proto::CardType::Min:
                {
                    std::vector<Card::ptr>& selfCards = self->GetCards();
                    std::vector<Card::ptr>& opponentCards = opponent->GetCards();
                    for(int i = 0; i < 3; i++)
                    {
                        if(selfCards[i]->GetWeight() == opponentCards[i]->GetWeight())
                        {
                            continue;
                        }
                        else if(selfCards[i]->GetWeight() > opponentCards[i]->GetWeight())
                        {
                            return self;
                        }
                        else
                        {
                            return opponent;
                        }
                    }
                }
            default:
                break;
        }
    }
    return self;
}

void FightHandler::Process(Player::ptr& player)
{
    switch (m_fightModel.fightcode())
    {
    case proto::PutStakes_CREQ:
        {
            proto::StakesRequest stakesRequest;
            stakesRequest.ParseFromArray(m_fightModel.msg().c_str(), m_fightModel.msg().size());
            MatchRoom::ptr room = RoomMgr::GetInstance()->GetRoom(player);
            int stakes = stakesRequest.stakes();
            PutStakesCREQ(player, room, stakes);
        }
        break;
    case proto::FightCode::LookCard_CREQ:
        {
            MatchRoom::ptr room = RoomMgr::GetInstance()->GetRoom(player);
            LookCardCREQ(player, room);
        }
        break;
    case proto::FightCode::GiveUpCard_CREQ:
        {
            proto::GiveUpRequest giveUpRequest;
            giveUpRequest.ParseFromArray(m_fightModel.msg().c_str(), m_fightModel.msg().size());
            MatchRoom::ptr room = RoomMgr::GetInstance()->GetRoom(player);
            room->AddToGiveUp(player->GetId());
            GiveUpCardCREQ(player, room, giveUpRequest.preplayerstakes());
        }
        break;
    case proto::FightCode::CompareCard_CREQ:
        {
            proto::CompareCardReuqest compareCardRequest;
            compareCardRequest.ParseFromArray(m_fightModel.msg().c_str(), m_fightModel.msg().size());
            MatchRoom::ptr room = RoomMgr::GetInstance()->GetRoom(player);

        }
        break;
    default:
        break;
    }
}